package com.gitee.wsl.io.api

import kotlinx.io.IOException
import kotlinx.io.RawSource

interface ByteSink {

    /**
     * Writes bytes from [source] array or its subrange to this sink.
     *
     * @param source the array from which bytes will be written into this sink.
     * @param startIndex the start index (inclusive) of the [source] subrange to be written, 0 by default.
     * @param endIndex the endIndex (exclusive) of the [source] subrange to be written, size of the [source] by default.
     *
     * @throws IndexOutOfBoundsException when [startIndex] or [endIndex] is out of range of [source] array indices.
     * @throws IllegalArgumentException when `startIndex > endIndex`.
     * @throws IllegalStateException when the sink is closed.
     * @throws IOException when some I/O error occurs.
     *
     * @sample kotlinx.io.samples.KotlinxIoCoreCommonSamples.writeByteArrayToSink
     */
    fun write(source: ByteArray, startIndex: Int = 0, endIndex: Int = source.size)

    /**
     * Removes all bytes from [source] and write them to this sink.
     * Returns the number of bytes read which will be 0 if [source] is exhausted.
     *
     * @param source the source to consume data from.
     *
     * @throws IllegalStateException when the sink or [source] is closed.
     * @throws IOException when some I/O error occurs.
     *
     * @sample kotlinx.io.samples.KotlinxIoCoreCommonSamples.transferFrom
     */
     fun transferFrom(source: RawSource): Long

    /**
     * Removes [byteCount] bytes from [source] and write them to this sink.
     *
     * If [source] will be exhausted before reading [byteCount] from it then an exception throws on
     * an attempt to read remaining bytes will be propagated to a caller of this method.
     *
     * @param source the source to consume data from.
     * @param byteCount the number of bytes to read from [source] and to write into this sink.
     *
     * @throws IllegalArgumentException when [byteCount] is negative.
     * @throws IllegalStateException when the sink or [source] is closed.
     * @throws IOException when some I/O error occurs.
     *
     * @sample kotlinx.io.samples.KotlinxIoCoreCommonSamples.writeSourceToSink
     */
     fun write(source: RawSource, byteCount: Long)

    /**
     * Writes a byte to this sink.
     *
     * @param byte the byte to be written.
     *
     * @throws IllegalStateException when the sink is closed.
     * @throws IOException when some I/O error occurs.
     *
     * @sample kotlinx.io.samples.KotlinxIoCoreCommonSamples.writeByte
     */
     fun writeByte(byte: Byte)

    /**
     * Writes two bytes containing [short], in the big-endian order, to this sink.
     *
     * @param short the short integer to be written.
     *
     * @throws IllegalStateException when the sink is closed.
     * @throws IOException when some I/O error occurs.
     *
     * @sample kotlinx.io.samples.KotlinxIoCoreCommonSamples.writeShort
     */
     fun writeShort(short: Short)

    /**
     * Writes four bytes containing [int], in the big-endian order, to this sink.
     *
     * @param int the integer to be written.
     *
     * @throws IllegalStateException when the sink is closed.
     * @throws IOException when some I/O error occurs.
     *
     * @sample kotlinx.io.samples.KotlinxIoCoreCommonSamples.writeInt
     */
     fun writeInt(int: Int)

    /**
     * Writes eight bytes containing [long], in the big-endian order, to this sink.
     *
     * @param long the long integer to be written.
     *
     * @throws IllegalStateException when the sink is closed.
     * @throws IOException when some I/O error occurs.
     *
     * @sample kotlinx.io.samples.KotlinxIoCoreCommonSamples.writeLong
     */
     fun writeLong(long: Long)

    /**
     * Writes all buffered data to the underlying sink, if one exists.
     * Then the underlying sink is explicitly flushed.
     *
     * @throws IllegalStateException when the sink is closed.
     * @throws IOException when some I/O error occurs.
     *
     * @sample kotlinx.io.samples.KotlinxIoCoreCommonSamples.flush
     */
     //fun flush()

}